//============================================================================
// Name        : LinuxThread.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include "pthread.h"
#include "stdlib.h"
#include "math.h"
#include "ThreadedQueue.h"
#include "sys/time.h"
#include <stdio.h>
#include <string.h>
using namespace std;


void* makeWork(void* queue)
{
   queueADT adt;
   adt = (queueADT)queue;
   printf("Producer Thread #%lu!\n", pthread_self());
   int fd = -1;
   fd = open("./corpus.out", O_RDONLY );
   int n_read = 0;
   int i = 0;
   int j = 0;
   char buffer[4096];
   char new_word[100];
   char dummy_finish[]="#";
   if ( fd )
   {
      while ( (n_read = read(fd, buffer, 4096)) != 0)
      {
         j = 0;
         for (i = 0; i < n_read; i++)
         {
            if (buffer[i] == '\n')
            {
               if ( i != j && ( i - j) < 100)
               {
                  buffer[i] = '\0';
                  strncpy(new_word, buffer+j, i-j);
                  new_word[i-j] = '\0';
                  push(adt, new_word);
                  j = i + 1;
               }
            }
         }
      }
   }
   printf("PUSH TERMINATION\n");
   close(fd);
   push(adt, dummy_finish);
   printf("Producer thread th %lu finished\n", pthread_self());
   pthread_exit(NULL);
}


void* getWork(void *queue)
{
   queueADT adt;
   adt = (queueADT)queue;
   while(!isTermination(adt))
   {
      queueElementT elem;
      wait_and_pop(adt, &elem);
   }


   printf("Consumer thread %lu finished\n" , pthread_self());
   pthread_exit(NULL);
}

int main() {
   cout << "!!!Producer Consumer!!!" << endl; // prints !!!Hello World!!!
   queueADT queue = QueueCreate();
   pthread_t pth[5];


   struct timeval tv_start,tv_stop;

   gettimeofday(&tv_start,NULL);

   pthread_create(&pth[0], NULL, getWork, (void *)queue);
   pthread_create(&pth[1], NULL, makeWork, (void *)queue);
   pthread_create(&pth[2], NULL, getWork, (void*)queue);
   pthread_create(&pth[3], NULL, getWork, (void*)queue);
   //
   pthread_join(pth[0], NULL);
   pthread_join(pth[1], NULL);
   pthread_join(pth[2], NULL);
   pthread_join(pth[3], NULL);

   gettimeofday(&tv_stop ,NULL);

   printf ("%ld,%06ld seconds\n",tv_stop.tv_sec-tv_start.tv_sec, tv_stop.tv_usec-tv_start.tv_usec);
   printf("FINISHED");
   QueueDestroy(queue);

   return 0;
}
